package com.jie.commonlib.network.http.utils

import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.*

/**
 * 获取类或接口上的泛型T
 * @author jie
 */
object GenericsUtils {
    /**
     * 获取接口上的第一个泛型集合
     */
    fun getInterfaceT(o: Any): ArrayList<Class<*>> {
        return getInterfaceT(o, 0)
    }

    /**
     * 获取接口上的泛型T
     *
     * @param o     接口
     * @param index 泛型索引
     */
    @JvmStatic
    fun getInterfaceT(o: Any, index: Int): ArrayList<Class<*>> {
        val types = o.javaClass.genericInterfaces
        val parameterizedType = types[index] as ParameterizedType
        val type = parameterizedType.actualTypeArguments[index]
        val classList = ArrayList<Class<*>>()
        checkType(type, index, classList)
        return classList
    }

    /**
     * 获取类上的泛型T
     *
     * @param o     接口
     * @param index 泛型索引
     */
    fun getClassT(o: Any, index: Int): Class<*> {
        val type = o.javaClass.genericSuperclass
        return if (type is ParameterizedType) {
            val actType = type.actualTypeArguments[index]
            checkType(actType, index)
        } else {
            val className = if (type == null) "null" else type.javaClass.name
            throw IllegalArgumentException(
                "Expected a Class, ParameterizedType"
                        + ", but <" + type + "> is of type " + className
            )
        }
    }

    /**
     * 递归找到最后一层泛型
     */
    private fun checkType(type: Type?, index: Int): Class<*> {
        return if (type is Class<*>) {
            type
        } else if (type is ParameterizedType) {
            val t = type.actualTypeArguments[index]
            checkType(t, index)
        } else {
            val className = if (type == null) "null" else type.javaClass.name
            throw IllegalArgumentException(
                "Expected a Class, ParameterizedType"
                        + ", but <" + type + "> is of type " + className
            )
        }
    }
    //    /**
    //     * 递归找到指定层级的泛型，若层级不够，则返回上一级的泛型
    //     * @param level 层级索引（暂时只支持 0、1，即第一层和第二层）
    //     */
    //    private static Class<?> checkType(Type type, int index, @Level int level) {
    //        if (type instanceof Class<?>) {
    //            return (Class<?>) type;
    //        } else if (type instanceof ParameterizedType) {
    //            if (level == Level.LEVEL_1) {
    //                return ((Class<?>) ((ParameterizedType) type).getRawType());
    //            } else {
    //                ParameterizedType pt = (ParameterizedType) type;
    //                Type t = pt.getActualTypeArguments()[index];
    //                return checkType(t, index, level == Level.LEVEL_LAST ? Level.LEVEL_LAST : Level.LEVEL_1);
    //            }
    //        } else {
    //            String className = type == null ? "null" : type.getClass().getName();
    //            throw new IllegalArgumentException("Expected a Class, ParameterizedType"
    //                    + ", but <" + type + "> is of type " + className);
    //        }
    //    }
    /**
     * 递归找到所有层级的泛型
     * @param type Type对象
     * @param index 泛型索引
     * @param classList 取到的泛型集合
     */
    private fun checkType(type: Type?, index: Int, classList: MutableList<Class<*>>) {
        if (type is Class<*>) {
            // 添加最后一层泛型
            classList.add(type)
        } else if (type is ParameterizedType) {
            val pt = type
            // 添加非最后一层泛型
            classList.add(pt.rawType as Class<*>)
            val t = pt.actualTypeArguments[index]
            checkType(t, index, classList)
        } else {
            val className = if (type == null) "null" else type.javaClass.name
            throw IllegalArgumentException(
                "Expected a Class, ParameterizedType"
                        + ", but <" + type + "> is of type " + className
            )
        }
    }
}